package com.w.picture.api.aliyunai.model;

import cn.hutool.core.annotation.Alias;
import lombok.Data;

import java.io.Serializable;

/**
 * 图像画面扩展请求模型
 * 注意:序列化反序列化的字段一定要和阿里云api接口保持一致
 *
 * @author wzp
 * @since 2025/1/25
 */
@Data
public class ImageOutPaintingRequest implements Serializable {

    /**
     * 调用模型。图像画面扩展模型为image-out-painting。
     */
    private String model = "image-out-painting";
    private Input input;
    private Parameters parameters;

    /**
     * 输入图像的基本信息，比如图像URL地址。
     */
    @Data
    public static class Input implements Serializable {
        /**
         * 图像URL地址或者图像base64数据。
         */
        @Alias("image_url")
        private String imageUrl;
    }

    /**
     * 图像处理参数。
     */
    @Data
    public static class Parameters implements Serializable {
        /**
         * 逆时针旋转角度。默认值为0，取值范围[0, 359]。
         * 需要与x_scale、y_scale参数或者top_offset、bottom_offset、left_offset 、right_offset参数搭配使用。
         */
        private Integer angle;

        /**
         * 图像宽高比。可选值有["", "1:1", "3:4", "4:3", "9:16", "16:9"]。
         * 默认为""，表示不设置输出图像的宽高比。
         * 相较于比例参数或者添加像素数参数，output_ratio参数的优先级最高。
         * 如果output_ratio取值不为空字符串，则使用该参数输出图像。
         */
        @Alias("output_ratio")
        private String outputRatio;

        /**
         * 图像居中，在水平方向上按比例扩展图像。
         * 默认值为1.0，取值范围[1.0, 3.0]。
         * 可以选择与y_scale参数搭配使用，但不能与top_offset、bottom_offset、left_offset 、right_offset这些参数同时使用。
         * 若同时配置，则x_scale、y_scale参数优先生效。
         */
        @Alias("x_scale")
        private Float xScale;

        /**
         * 图像居中，在垂直方向上按比例扩展图像。
         * 默认值为1.0，取值范围[1.0, 3.0]。
         * 可以选择与x_scale参数搭配使用，但不能与top_offset、bottom_offset、left_offset、right_offset这些参数同时使用。
         * 若同时配置，则x_scale、y_scale参数优先生效。
         */
        @Alias("y_scale")
        private Float yScale;

        /**
         * 在图像上方添加像素。
         * 默认值为0，取值限制top_offset+bottom_offset < 3×输入图像高度。
         * 可以选择与bottom_offset、left_offset 、right_offset参数搭配使用，但不能与x_scale、y_scale这些参数同时使用。
         * 若同时配置，则x_scale、y_scale参数优先生效。
         */
        @Alias("top_offset")
        private Integer topOffset;

        /**
         * 在图像下方添加像素。
         * 默认值为0，取值限制top_offset+bottom_offset < 3×输入图像高度。
         * 可以选择与top_offset、left_offset 、right_offset参数搭配使用，但不能与x_scale、y_scale这些参数同时使用。
         * 若同时配置，则x_scale、y_scale参数优先生效。
         */
        @Alias("bottom_offset")
        private Integer bottomOffset;

        /**
         * 在图像左侧添加像素。
         * 默认值为0，扩展限制left_offset+right_offset < 3×输入图像宽度。
         * 可以选择与top_offset、bottom_offset、right_offset参数搭配使用，但不能与x_scale、y_scale这些参数同时使用。
         * 若同时配置，则x_scale、y_scale参数优先生效。
         */
        @Alias("left_offset")
        private Integer leftOffset;

        /**
         * 在图像右侧添加像素。
         * 默认值为0，扩展限制left_offset+right_offset < 3×输入图像宽度。
         * 可以选择与top_offset、bottom_offset、left_offset参数搭配使用，但不能与x_scale、y_scale这些参数同时使用。
         * 若同时配置，则x_scale、y_scale参数优先生效。
         */
        @Alias("right_offset")
        private Integer rightOffset;

        /**
         * 开启图像最佳质量模式。默认值为false，减少图像生成的等待时间。
         * 如果需要更多图像细节，可以设置为true，但耗时会成倍增加。
         */
        @Alias("best_quality")
        private Boolean bestQuality;

        /**
         * 限制模型生成的图像文件大小。默认值为true，限制为：
         * 当输入图像单边长度<=10000，输出图像文件大小在5MB以下
         * 当输入图像单边长度>10000，输出图像文件大小在10MB以下
         * 也可以设置为false，不压缩模型生成的图像文件，搭配 best_quality 参数可获得高质量图像。
         */
        @Alias("limit_image_size")
        private Boolean limitImageSize;

        /**
         * 添加Generated by AI水印。默认值为True，在输出图像左下角处添加水印。
         */
        @Alias("add_watermark")
        private Boolean addWatermark;

        // 手动提供get,set方法
        // 这里之所以要手动的显示提供get,set方法，是为了解决序列化时，无法序列化null的问题,,默认生成的是getXScale()
        // 还有一个方法:         @JsonProperty("xScale") ,,但是为了方便和阿里云api接口保持一致,所以手动提供get,set方法
        public Float getxScale() {
            return xScale;
        }

        public Float getyScale() {
            return yScale;
        }

        public void setxScale(Float xScale) {
            this.xScale = xScale;
        }

        public void setyScale(Float yScale) {
            this.yScale = yScale;
        }
    }
}